#ifdef	ADI_OLD

#include "Job.h"
#include "ThreadsPool.h"

#define max(i, j) ((i >= j) ? i : j)

Job::Job(Job::JobType _type, uint _inputFileIndx, uint _seqind, CompareSeqs *_cmps, uint _jobIndex) :
	type(_type),
	done(false),
	inputFileIndx(_inputFileIndx),
	seqind(_seqind),
	cmps(_cmps),
	jobIndex(_jobIndex)
{
}

Job::~Job()
{
	delete cmps;
}

void Job::process()
{
	switch (type)
	{
	case COMPARE_SEQS:
		processCompares();
		break;
	case FILE_READ:
		readFile();
		break;
	default:
		/* Error - should not reach here */
		cout << "ERROR!!!!!!!!!" << endl;
		break;
	}
}


void Job::processCompares()
{
	// Iterate over the reference dynamic-bitset and find the positions to search in
	size_t curRefBegin;
	size_t refLength = refSeq->getLength();
	size_t inputLength = cmps->is->length();
	size_t curRefPos = 0;
	while (1)
	{
		// Compare a sub-reference sequence (which starts in curRefPos) with the input sequence
		curRefPos = cmps->refPositions->getNextBitSet(curRefPos) + minMatchLength;
		if (curRefPos == (size_t)-1)
		{
			// No more bits are set, done processing the job, delete the cmps
			delete cmps;
			return;
		}
		curRefBegin = curRefPos;
		size_t curInputPos = cmps->inputPos + minMatchLength;
		while ((curRefPos != (size_t)-1) && (curInputPos != (size_t)-1))
		{
			// We first compare the data in blocks and after we find a non-matching block, we compare that block char-by-char
			// We know that the first minMatchLength bits are the same, so lets check the next block
			SeqBlock nextRefBlock = refSeq->getBlock(curRefPos);
			SeqBlock nextInputBlock = cmps->is->getBlock(curInputPos);
			if (nextRefBlock != nextInputBlock)
			{
				// Find out why they are different
				ulong maskIndex = 1;
				int i = 1;
				for (; i < CHARS_PER_BLOCK; i++)
				{
					SeqBlock upToRef = nextRefBlock & ((1UL << ((i << 1) + 1)) - 1); // nextRefBlock & ((1UL << (i*2 + 1)) - 1)
					SeqBlock upToInput = nextInputBlock & ((1UL << ((i << 1) + 1)) - 1); // nextRefBlock & ((1UL << (i*2 + 1)) - 1)
					if (upToRef != upToInput)
					{
						// reference and input differ in char i
						break;
					}
				}
				
				// reference and input differ in char i
				// TODO - stopped here

				Match *curMatch = new Match(curRefBegin - minMatchLength, endRefPos, );
				break;
			}
			curRefPos += CHARS_PER_BLOCK;
			curInputPos += CHARS_PER_BLOCK;
		}
	}


}

#ifdef	ADI_OLD
void Job::processDiags()
{
	if (done)
		return;
		
 	InputSequence &seq = inSeqsSeq[inputFileIndx].getSequence(seqind);
	/* Process all diagonals in the i'th diagonal stretch */
	for (uint k = diags->first; k <= diags->last; k++)
	{
		size_t refInd = 0, inseqInd = 0;
		size_t limit, runner;
		if (diags->isRefSeqIndx) 
		{
			refInd = runner = k;
			limit = refSeq->getLength();
		}
		else
		{
			inseqInd = runner = k;
			limit = seq.getLength();
		}

		size_t currSeq = 0;
		size_t sRef = refInd+1;
		size_t sInseq =  inseqInd+1;
		while (runner < limit)
		{
			if (refSeq->getBit(seq.getCharAsShort(inseqInd), refInd) == 1)
			{
				currSeq++;
			}
			else /* current sequence ended */
			{
				if (currSeq >= minMatchLength)
					seq.addMatch(jobIndex, new Match(sRef, refInd, sInseq, inseqInd));
				/* +1 for the indexing vs counting gap 
				   +1 as the match will be in the next index, it any */
				sRef = refInd+2;
				sInseq =  inseqInd+2;
				currSeq = 0;
			}
			refInd++;
			inseqInd++;
			runner++;
		}
		/* in case current diagonal ended with a sequence */
		if (currSeq >= minMatchLength)
			seq.addMatch(jobIndex, new Match(sRef, refInd, sInseq, inseqInd));
	}
	
	seq.notifyDone();
	done = true;
}
#endif	/* ADI_OLD */

void Job::readFile()
{
	ifstream inputFile(inSeqsSeq[inputFileIndx].getFilename() ,ios::in);
	// Just parse the file (it will automatically generate jobs
	inSeqsSeq[inputFileIndx].parseFile(inputFile);
}

#ifdef	ADI_OLD		
void Job::readFile()
{
	ifstream inputFile(inSeqsSeq[inputFileIndx].getFilename() ,ios::in);
		
	while (!inSeqsSeq[inputFileIndx].doneReading())
	{
		int newseqind = inSeqsSeq[inputFileIndx].addOneSequence(inputFile);
		InputSequence &newseq = inSeqsSeq[inputFileIndx].getSequence(newseqind);
		int perSeqJobsCount = 0;
		
#ifdef	DEBUG
			newseq.print();
#endif	/* DEBUG */
		
		/* create jobs to process the sequence */
		/* add Jobs with diagonals according to ref string (end to begining) */
		int temp1 = refSeq->getLength() - minMatchLength - JOB_SIZE;
		int temp2 = refSeq->getLength() - minMatchLength;
		int currStartDiag = max(0, temp1); /* ???????????????????? WHY? WHY? WHY? */
		int currEndDiag = max(0, temp2);
		while (currStartDiag < currEndDiag)
		{
			Job *newJob = new Job(DIAGS_JOB, 
									inputFileIndx, 
									newseqind, 
									new DiagStretch(true, currStartDiag, currEndDiag),
									perSeqJobsCount++);
			newseq.notifyJobAdd();
			pool->addJob(newJob);
			
#ifdef	DEBUG
			cout << "Added ref string diagonal: " << currStartDiag << " to " << currEndDiag << endl;
#endif	/* DEBUG */
			
			temp1 = currStartDiag-1;
			temp2 = currStartDiag-JOB_SIZE;
			currEndDiag = max(0, temp1);
			currStartDiag = max(0, temp2);
		}
		
		/* add Jobs with diagonals according to input string (begining to end) */
		temp1 = newseq.getLength() - minMatchLength - JOB_SIZE;
		temp2 = newseq.getLength() - minMatchLength;
		currStartDiag = max(1, temp1);
		currEndDiag = max(1, temp2);
		while (currStartDiag < currEndDiag)
		{
			Job *newJob = new Job(DIAGS_JOB, 
													inputFileIndx, 
													newseqind,
													new DiagStretch(false, currStartDiag, currEndDiag),
													perSeqJobsCount++);
			newseq.notifyJobAdd();
			pool->addJob(newJob);
			
#ifdef	DEBUG
			cout << "Added input string diagonal: " << currStartDiag << " to " << currEndDiag << endl;
#endif	/* DEBUG */
			
			temp1 = currStartDiag-1;
			temp2 = currStartDiag-JOB_SIZE;
			currEndDiag = max(1, temp1);
			currStartDiag = max(1, temp2);
		}
		
		newseq.notifyLoaded();
	}
}
#endif	/* ADI_OLD */

#endif /* ADI_OLD */
